qtre.postProcessing = {

	index : 0,

	rootNode : null,

	passes : [],

	createPostProcessing : function(program, renderToBuffer){
		var camera = qtre.sceneManager.createCamera("PP_"+this.index, {
			eye : [0, 0, 1],
			target : [0, 0, 0],
			up : [0, 1, 0],
			left : -1,
			right : 1,
			top : 1,
			bottom : -1,
			near : -1,
			far : 1
		})
		if(!this.rootNode){
			this.rootNode = qtre.sceneManager.createSceneNode("PP_");
		}
		this.rootNode.attachObject(camera);

		if(renderToBuffer){
			var fbo = tdl.framebuffers.createFramebuffer(1024, 1024);
			fbo.unbind();
			camera.addRenderBeginCallback(function(){
				fbo.bind();
			})
			camera.addRenderEndCallback(function(){
				fbo.unbind();
			})
		}else{
			fbo = null;
		}

		var material = qtre.sceneManager.createMaterial("PP_"+this.index, program);
		material.bindCamera(camera);
		var arrays = tdl.primitives.createPlane(2, 2, 1, 1);
		tdl.primitives.reorient(arrays,
			[1, 0, 0, 0,
			0, 0, 1, 0,
			0, -1, 0, 0,
			0, 0, 0.9999, 1]);
		delete arrays.normal;
		var renderable = qtre.sceneManager.createRenderable("PP_"+this.index, arrays);
		renderable.bindMaterial(material);
		var sceneNode = qtre.sceneManager.createSceneNode("PP_"+this.index);
		sceneNode.attachObject(renderable);

		this.index++;

		var pass = {
			"camera" : camera,
			"renderable" : renderable,
			"material" : material,
			"fbo" : fbo
		}
		this.passes.push(pass);

		return pass;
	},

	vertexShader : function(){
		return "attribute vec4 position;\n\
				attribute vec2 texCoord;\n\
				varying vec4 v_position;\n\
				varying vec2 v_uv;\n\
				void main() {\n\
					v_position = position;\n\
					v_uv = vec2(texCoord.x, 1.0 - texCoord.y);\n\
					gl_Position = position;\n\
				}"
	}
}

qtre.postProcessing.base = function(options, renderToBuffer){

	this.passes = [];

	this.options = [];
	
	var options = options || {};
	var opt_default = {
		"blurFactor" : 1
	}
	for(var name in opt_default){
		this.options[name] = options[name] || opt_default[name];
	}

}
/**************************************
 * some common post processing
 *************************************/
qtre.postProcessing.gaussBlur = function(fbo, options, renderToBuffer){
	qtre.postProcessing.base.call(this, options, renderToBuffer);
	//horizontal pass
	var pixelShaderHorizontal = "#ifdef GL_ES\n\
							precision highp float;\n\
							#endif\n\
							uniform sampler2D RTScene; // the texture with the scene you want to blur\n\
							uniform float blurFactor;\n\
							varying vec2 v_uv;\n\
							const float blurSize = 1.0/1024.0;\n\
							void main(void)\n\
							{\n\
							   vec4 sum = vec4(0.0);\n\
							   // blur in y (vertical)\n\
							   // take nine samples, with the distance blurSize between them\n\
							   sum += texture2D(RTScene, vec2(v_uv.x - 4.0*blurSize*blurFactor, v_uv.y)) * 0.05;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x - 3.0*blurSize*blurFactor, v_uv.y)) * 0.09;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x - 2.0*blurSize*blurFactor, v_uv.y)) * 0.12;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x - blurSize*blurFactor, v_uv.y)) * 0.15;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x, v_uv.y)) * 0.16;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x + blurSize*blurFactor, v_uv.y)) * 0.15;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x + 2.0*blurSize*blurFactor, v_uv.y)) * 0.12;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x + 3.0*blurSize*blurFactor, v_uv.y)) * 0.09;\n\
							   sum += texture2D(RTScene, vec2(v_uv.x + 4.0*blurSize*blurFactor, v_uv.y)) * 0.05;\n\
							   gl_FragColor = sum;\n\
							}";
	var program = tdl.programs.loadProgram(qtre.postProcessing.vertexShader(), pixelShaderHorizontal);
	var passHorizontal = qtre.postProcessing.createPostProcessing(program, true);
	passHorizontal.material.updateUniforms(this.options);
	passHorizontal.material.updateUniforms({
		"RTScene" : fbo.texture
	})
	this.passes.push(passHorizontal);
	//vertical pass
	var pixelShaderVertical = "\n\
							#ifdef GL_ES\n\
							precision highp float;\n\
							#endif\n\
							uniform sampler2D RTBlurH; // this should hold the texture rendered by the horizontal blur pass\n\
							uniform float blurFactor;\n\
							varying vec2 v_uv;\n\
							const float blurSize = 1.0/1024.0;\n\
							void main(void)\n\
							{\n\
							   vec4 sum = vec4(0.0);\n\
							   // blur in y (vertical)\n\
							   // take nine samples, with the distance blurSize between them\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y - 4.0*blurSize*blurFactor)) * 0.05;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y - 3.0*blurSize*blurFactor)) * 0.09;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y - 2.0*blurSize*blurFactor)) * 0.12;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y - blurSize*blurFactor)) * 0.15;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y)) * 0.16;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y + blurSize*blurFactor)) * 0.15;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y + 2.0*blurSize*blurFactor)) * 0.12;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y + 3.0*blurSize*blurFactor)) * 0.09;\n\
							   sum += texture2D(RTBlurH, vec2(v_uv.x, v_uv.y + 4.0*blurSize*blurFactor)) * 0.05;\n\
							   gl_FragColor = sum;\n\
							}"
	var program = tdl.programs.loadProgram(qtre.postProcessing.vertexShader(), pixelShaderVertical);
	var passVertical = qtre.postProcessing.createPostProcessing(program);
	passVertical.material.updateUniforms(this.options);
	passVertical.material.updateUniforms({
		"RTBlurH" : passHorizontal.fbo.texture
	})
	this.passes.push(passVertical);
}
qtre.postProcessing.gaussBlur.prototype = new qtre.postProcessing.base();